/*
 * libArchivoConfiguracion.c
 *
 *  Created on: 27/01/2012
 *      Author: utnso
 */

#include "libArchivoConfiguracion.h"

//TODO modificar los parametros de leerArchivoConfiguracion
uint8_t leerArchivoConfiguracion(archConfig_t* archConfig, uint8_t imprimirDebug) {
	archConfigAux_t archConfigAux;
	archConfigAux.IP.id = (char*) malloc(3);
	memset(archConfigAux.IP.id, '\0', 3);
	strcpy(archConfigAux.IP.id, "IP");
	archConfigAux.IP.valor = NULL;

	archConfigAux.puerto.id = (char*) malloc(7);
	memset(archConfigAux.puerto.id, '\0', 7);
	strcpy(archConfigAux.puerto.id, "Puerto");
	archConfigAux.puerto.valor = -1;

	archConfigAux.cantConexiones.id = (char*) malloc(27);
	memset(archConfigAux.cantConexiones.id, '\0', 27);
	strcpy(archConfigAux.cantConexiones.id, "MaximaCantidaddeConexiones");
	archConfigAux.cantConexiones.valor = -1;

	archConfigAux.retardo.id = (char*) malloc(8);
	memset(archConfigAux.retardo.id, '\0', 8);
	strcpy(archConfigAux.retardo.id, "Retardo");
	archConfigAux.retardo.valor = -1;

	archConfigAux.pathDisco.id = (char*) malloc(12);
	memset(archConfigAux.pathDisco.id, '\0', 12);
	strcpy(archConfigAux.pathDisco.id, "PathdeDisco");
	archConfigAux.pathDisco.valor = NULL;

	archConfigAux.nivelLog.id = (char*) malloc(14);
	memset(archConfigAux.nivelLog.id, '\0', 14);
	strcpy(archConfigAux.nivelLog.id, "NiveldeLogueo");
	archConfigAux.nivelLog.valor = -1;

	if(imprimirDebug){
		printf("Se intentara abrir el archivo de configuracion.\n");
	}
	FILE* fp;
	fp = fopen(PATH_ARCHIVO_CONFIGURACION, "r");
	if (fp != NULL) {
		//EL ARCHIVO DE CONFIGURACION FUE ABIERTO EXITOSAMENTE
		if (imprimirDebug) {
			printf("El archivo de configuracion fue abierto exitosamente.\n");
		}
		fseek(fp, 0, SEEK_SET);
		uint8_t finLectura = 0;
		while (!finLectura) {
			if (imprimirDebug) {
				printf("Se intentara leer una linea del archivo de configuracion.\n");
			}
			finLectura = leerLinea(fp, &archConfigAux, imprimirDebug);
		}
		if (finLectura == 1) {
			//EL FORMATO DEL ARCHIVO ES CORRECTO
			if (imprimirDebug) {
				printf("Se termino de leer el archivo.\n");
			}
			uint8_t archivoIncompleto = archivoDeConfiguracionNoCompleto(archConfigAux);
			fclose(fp);
			if (!archivoIncompleto) {
				if (imprimirDebug) {
					printf("El archivo contenia todos los datos esperados.\n");
				}
				(*archConfig).IP = (char*) malloc(strlen(archConfigAux.IP.valor) + 1);
				memset((*archConfig).IP, '\0', strlen(archConfigAux.IP.valor) + 1);
				strcpy((*archConfig).IP, archConfigAux.IP.valor);
				(*archConfig).puerto = (int32_t) archConfigAux.puerto.valor;
				(*archConfig).cantConexiones = (uint8_t) archConfigAux.cantConexiones.valor;
				(*archConfig).retardo = (uint32_t) archConfigAux.retardo.valor;
				(*archConfig).pathDisco = (char*) malloc(strlen(archConfigAux.pathDisco.valor) + 1);
				memset((*archConfig).pathDisco, '\0', strlen(archConfigAux.pathDisco.valor) + 1);
				strcpy((*archConfig).pathDisco, archConfigAux.pathDisco.valor);
				(*archConfig).nivelLog = (uint8_t) archConfigAux.nivelLog.valor;
				return 0;
			} else {
				printf("------------------------------------------------------------\n");
				printf("--                         ERROR                          --\n");
				printf("------------------------------------------------------------\n");
				printf("El archivo no contenia todos los datos esperados.\n");
				printf("------------------------------------------------------------\n");
				printf("\n");
				return 1;
			}
		} else if (finLectura == 2) {
			//EL FORMATO DEL ARCHIVO ES INCORRECTO
			printf("------------------------------------------------------------\n");
			printf("--                         ERROR                          --\n");
			printf("------------------------------------------------------------\n");
			printf("El formato del archivo de configuracion es incorrecto.\n");
			printf("El formato debe ser el siguiente:\n");
			printf("IP: <Valor>\n");
			printf("Puerto: <Valor>\n");
			printf("Maxima Cantidad de Conexiones: <Valor>\n");
			printf("Nivel de Logueo: <Valor>@\n");
			printf("Notas:\n");
			printf("Los espacios seran ignorados tanto en las Id como el el valor de los datos.\n");
			printf("El caracter @ debe marcar el fin del archivo.\n");
			printf("------------------------------------------------------------\n");
			printf("\n");
			fclose(fp);
			return 2;
		} else {
			return 4;
		}
	} else {
		//EL ARCHIVO DE CONFIGURACION NO PUDO SER ABIERTO
		printf("------------------------------------------------------------\n");
		printf("--                         ERROR                          --\n");
		printf("------------------------------------------------------------\n");
		printf("El archivo de configuracion no pudo ser abierto.\n");
		printf("Compruebe que se encuentre en [%s].\n", PATH_ARCHIVO_CONFIGURACION);
		printf("------------------------------------------------------------\n");
		printf("\n");
		return 3;
	}
}

uint8_t leerLinea(FILE* fp, archConfigAux_t* archConfigAux, uint8_t imprimirDebug) {
	char *buffer = (char*) malloc(MAX_LINEA_ARCHIVO_CONFIGURACION + 1);
	memset(buffer, '\0', MAX_LINEA_ARCHIVO_CONFIGURACION + 1);
	char caracter;
	fread(&caracter, 1, 1, fp);
	uint8_t pos;
	for (pos = 0; pos < MAX_LINEA_ARCHIVO_CONFIGURACION && caracter != '\n' && caracter != '@'; pos++) {
		buffer[pos] = caracter;
		fread(&caracter, 1, 1, fp);
	}
	if (imprimirDebug) {
		printf("Se leyo la linea [%s].\n", buffer);
	}
	uint8_t errorDeFormato;
	errorDeFormato = parsearLinea(buffer, archConfigAux, imprimirDebug);
	if (errorDeFormato) {
		free(buffer);
		return 2;
	} else if (caracter == '@') {
		free(buffer);
		return 1;
	} else {
		free(buffer);
		return 0;
	}
}

uint8_t parsearLinea(char* buffer, archConfigAux_t* archConfigAux, uint8_t imprimirDebug) {
	char *id;
	char *valor;
	eliminarEspaciosDeCadena(&buffer);
	uint8_t errorDeFormato = 0;
	errorDeFormato = separarIdDeValor(buffer, &id, &valor);
	if (!errorDeFormato) {
		if (strcmp(id, (*archConfigAux).IP.id) == 0) {
			uint8_t i;
			for (i = 0; valor[i] != '\0'; i++)
				;
			(*archConfigAux).IP.valor = (char*) malloc(i + 1);
			memset((*archConfigAux).IP.valor, '\0', i + 1);
			for (i = 0; valor[i] != '\0'; i++) {
				(*archConfigAux).IP.valor[i] = valor[i];
			}
			if (imprimirDebug) {
				printf("Se ha asignado a la variable con id [%s] el valor [%s].\n", (*archConfigAux).IP.id, (*archConfigAux).IP.valor);
			}
			return 0;
		} else if (strcmp(id, (*archConfigAux).puerto.id) == 0) {
			(*archConfigAux).puerto.valor = atoi(valor);
			if (imprimirDebug) {
				printf("Se ha asignado a la variable con id [%s] el valor [%d].\n", (*archConfigAux).puerto.id, (*archConfigAux).puerto.valor);
			}
			return 0;
		} else if(strcmp(id, (*archConfigAux).cantConexiones.id) == 0) {
			(*archConfigAux).cantConexiones.valor = atoi(valor);
			if (imprimirDebug) {
				printf("Se ha asignado a la variable con id [%s] el valor [%d].\n", (*archConfigAux).cantConexiones.id, (*archConfigAux).cantConexiones.valor);
			}
			return 0;
		}  else if(strcmp(id, (*archConfigAux).retardo.id) == 0) {
			(*archConfigAux).retardo.valor = atoi(valor);
			if (imprimirDebug) {
				printf("Se ha asignado a la variable con id [%s] el valor [%d].\n", (*archConfigAux).retardo.id, (int32_t)(*archConfigAux).retardo.valor);
			}
			return 0;
		}else if (strcmp(id, (*archConfigAux).pathDisco.id) == 0) {
			uint8_t i;
			for (i = 0; valor[i] != '\0'; i++)
				;
			(*archConfigAux).pathDisco.valor = (char*) malloc(i + 1);
			memset((*archConfigAux).pathDisco.valor, '\0', i + 1);
			for (i = 0; valor[i] != '\0'; i++) {
				(*archConfigAux).pathDisco.valor[i] = valor[i];
			}
			if (imprimirDebug) {
				printf("Se ha asignado a la variable con id [%s] el valor [%s].\n", (*archConfigAux).pathDisco.id, (*archConfigAux).pathDisco.valor);
			}
			return 0;
		}else if(strcmp(id, (*archConfigAux).nivelLog.id) == 0) {
			(*archConfigAux).nivelLog.valor = atoi(valor);
			if (imprimirDebug) {
				printf("Se ha asignado a la variable con id [%s] el valor [%d].\n", (*archConfigAux).nivelLog.id, (*archConfigAux).nivelLog.valor);
			}
			return 0;
		} else {
			return 1;
		}
	} else {
		return 2;
	}
}

void eliminarEspaciosDeCadena(char** buffer) {
	uint8_t i;
	uint8_t j;
	for (i = 0, j = 0; j < MAX_LINEA_ARCHIVO_CONFIGURACION; j++) {
		if ((*buffer)[j] != ' ') {
			(*buffer)[i] = (*buffer)[j];
			i++;
		}
	}
}

uint8_t separarIdDeValor(char* buffer, char** id, char** valor) {
	uint8_t i;
	for (i = 0; i < MAX_LINEA_ARCHIVO_CONFIGURACION && buffer[i] != ':' && buffer[i] != '\0'; i++)
		;
	if (buffer[i] == ':') {
		*id = (char*) malloc(i + 1);
		memset(*id, '\0', i + 1);
		for (i = 0; buffer[i] != ':'; i++) {
			(*id)[i] = buffer[i];
		}
		i++;
		uint8_t j;
		for (j = i; j < MAX_LINEA_ARCHIVO_CONFIGURACION && buffer[j] != '\0'; j++)
			;
		*valor = (char*) malloc(j - i + 1);
		memset(*valor, '\0', j - i + 1);
		for (j = 0; buffer[i] != '\0'; i++, j++) {
			(*valor)[j] = buffer[i];
		}
		return 0;
	} else {
		return 2;
	}
}

uint8_t archivoDeConfiguracionNoCompleto(archConfigAux_t archConfigAux) {
	if (archConfigAux.IP.valor != NULL && archConfigAux.puerto.valor != -1 && archConfigAux.cantConexiones.valor != -1 && archConfigAux.retardo.valor != -1 && archConfigAux.pathDisco.valor != NULL && archConfigAux.nivelLog.valor != -1) {
		return 0;
	} else {
		return 2;
	}
}
